package com.lwj.diao;

import com.lwj.diao.Utils.UtilClassLoaderExpand;
import com.lwj.diao.Utils.UtilClass;
import com.lwj.diao.Utils.UtilJar;
import com.lwj.diao.Utils.UtilOut;
import com.sun.net.httpserver.HttpExchange;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;

public class Htmls {
    public static Charset UTF8_CS;
    private static final String UTF8 = "utf-8";
    public static StringBuilder HTML_WELCOME = new StringBuilder();
    public static StringBuilder HTML_EXECUTOR = new StringBuilder();;
    public static StringBuilder HTML_INDEX = new StringBuilder();;
    private static final String FLAG_RESULT = "flag_result";
    public static Map<String, InputStream> inputs;

    public static void init() throws IOException {
        Locale.setDefault(Locale.US);
        UTF8_CS = Charset.forName(UTF8);
//        HTML_WELCOME = Htmls.loadHtml("welcome.html");
//        HTML_EXECUTOR = Htmls.loadHtml("result.html");
//        HTML_INDEX = Htmls.loadHtml("index.html");
    }

    private static StringBuilder loadHtml(String html) throws IOException {
        System.out.println("-------------------start-----------------------");
        File htmlFile = new File(UtilJar.JAR_DIR + "web/" + html);
        if (!htmlFile.exists()) {
            htmlFile = new File("src/" + html);
        }
        if (htmlFile.exists() && htmlFile.isDirectory()) {
            return Htmls.readStream(new FileInputStream(htmlFile));
        }
        System.out.println("end---------------------end---------------------end");
        return Htmls.readStream(UtilJar.getProFileByPath(html));
    }

    public static Map<String, String> convertStream2Params(HttpExchange exchange) throws IOException {
        String content = Htmls.readStream(exchange.getRequestBody()).toString();
        String[] paramEntries = content.split("&");
        if (paramEntries == null) {
            return null;
        }
        HashMap<String, String> paramMap = new HashMap<String, String>(paramEntries.length);
        for (String paramEntry : paramEntries) {
            int i = paramEntry.indexOf("=");
            paramMap.put(paramEntry.substring(0, i), URLDecoder.decode(paramEntry.substring(i + 1, paramEntry.length()), UTF8));
        }
        return paramMap;
    }

    private static StringBuilder readStream(InputStream inStream) throws IOException {
        String line;
        StringBuilder content = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, UTF8_CS));
        while ((line = reader.readLine()) != null) {
            content.append(line + "\n");
        }
        reader.close();
        return content;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public static String parseExecuteResult(String resultHtml, String source, boolean isHtml) {
        ByteArrayOutputStream bos;
        PrintWriter writer;
        String className = UtilClass.parseClassName(source);
        boolean compilerResult = UtilClass.compile(className, source, writer = new PrintWriter(bos = new ByteArrayOutputStream(), true));
        if (compilerResult) {
            PrintStream exePrintStream = new PrintStream(bos, true);
            System.setOut(exePrintStream);
            System.setErr(exePrintStream);
            try {
                UtilClassLoaderExpand clod = new UtilClassLoaderExpand();
                clod.setLocation(UtilJar.JAR_DIR);
                Class<?> remoteClass = clod.findClass(className.substring(className.lastIndexOf(".") + 1));
                Method main = remoteClass.getDeclaredMethod("main", String[].class);
                main.invoke(null, new Object[]{null});
                exePrintStream.close();
            }
            catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | NoSuchMethodException | SecurityException | InvocationTargetException e) {
                e.printStackTrace();
            }
            finally {
                System.setOut(UtilOut.OUT);
                System.setErr(UtilOut.ERR);
            }
        }
        String exeLog = Htmls.readPrintLog(bos);
        writer.close();
        if (isHtml) {
            resultHtml = resultHtml.replaceAll(FLAG_RESULT, Matcher.quoteReplacement(exeLog));
            return resultHtml;
        }
        return exeLog;
    }

    public static String readPrintLog(ByteArrayOutputStream bos) {
        String log = new String(bos.toByteArray());
        return log;
    }

    static {
        inputs = new HashMap<String, InputStream>();
    }
}
